package timing.ukulele.flow.extention;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.activiti.bpmn.model.*;
import org.activiti.editor.language.json.converter.UserTaskJsonConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class MyUserTaskJsonConverter extends UserTaskJsonConverter implements UserTaskExtensionElementProperty {
    @Override
    protected void convertElementToJson(ObjectNode propertiesNode, BaseElement baseElement) {
        super.convertElementToJson(propertiesNode, baseElement);
        UserTask userTask = (UserTask) baseElement;
        //解析
        Map<String, List<ExtensionElement>> customerProperties = userTask.getExtensionElements();
        if (!CollectionUtils.isEmpty(customerProperties) && customerProperties.containsKey(elememt)) {
            ExtensionElement e = customerProperties.get(elememt).get(0);
            Map<String, List<ExtensionAttribute>> attributes = e.getAttributes();
            attributes.forEach((key, attr) -> {
                for (ExtensionAttribute extensionAttribute : attr) {
                    setPropertyValue(extensionAttribute.getName(), extensionAttribute.getValue(), propertiesNode);
                }
            });
        }
        // TODO 暂时放在后端添加 考虑后续能否前端配置
        MultiInstanceLoopCharacteristics loopCharacteristics = userTask.getLoopCharacteristics();
        if (loopCharacteristics != null) {
            ObjectNode multiNode = new ObjectNode(JsonNodeFactory.instance);
            multiNode.put("sequential", loopCharacteristics.isSequential());
            setPropertyValue(multiInstanceLoopCharacteristics, multiNode.toString(), propertiesNode);
        }
    }

    @Override
    protected FlowElement convertJsonToElement(JsonNode elementNode, JsonNode modelNode, Map<String, JsonNode> shapeMap) {
        FlowElement flowElement = super.convertJsonToElement(elementNode,
                modelNode, shapeMap);
        //解析新增属性的业务逻辑
        UserTask userTask = (UserTask) flowElement;

        ExtensionElement ee = new ExtensionElement();
        ee.setName("activiti:" + elememt);
        ee.setNamespacePrefix("activiti");
        Map<String, List<ExtensionAttribute>> attributes = new HashMap<>();

//        actionList
        String propertyActionList = getPropertyValueAsString(actionList, elementNode);
        if (StringUtils.hasLength(propertyActionList)) {
            ExtensionAttribute actionListAttr = new ExtensionAttribute();
            actionListAttr.setName(actionList);
            actionListAttr.setValue(propertyActionList);
            List<ExtensionAttribute> actionListAttrList = new ArrayList<>(1);
            actionListAttrList.add(actionListAttr);
            attributes.put(actionList, actionListAttrList);
        }

//        taskType
        String propertyTaskType = getPropertyValueAsString(taskType, elementNode);
        if (StringUtils.hasLength(propertyTaskType)) {
            ExtensionAttribute taskTypeAttr = new ExtensionAttribute();
            taskTypeAttr.setName(taskType);
            taskTypeAttr.setValue(propertyTaskType);
            List<ExtensionAttribute> taskTypeAttrList = new ArrayList<>(1);
            taskTypeAttrList.add(taskTypeAttr);
            attributes.put(taskType, taskTypeAttrList);
        }

//        proportion
        String propertyProportion = getPropertyValueAsString(proportion, elementNode);
        if (StringUtils.hasLength(propertyProportion)) {
            ExtensionAttribute proportionAttr = new ExtensionAttribute();
            proportionAttr.setName(proportion);
            proportionAttr.setValue(propertyProportion);
            List<ExtensionAttribute> proportionAttrList = new ArrayList<>(1);
            proportionAttrList.add(proportionAttr);
            attributes.put(proportion, proportionAttrList);
        }

//        formName
        String propertyFormName = getPropertyValueAsString(formName, elementNode);
        if (StringUtils.hasLength(propertyFormName)) {
            ExtensionAttribute formNameAttr = new ExtensionAttribute();
            formNameAttr.setName(formName);
            formNameAttr.setValue(propertyFormName);
            List<ExtensionAttribute> formNameAttrList = new ArrayList<>(1);
            formNameAttrList.add(formNameAttr);
            attributes.put(formName, formNameAttrList);
        }

//        selectFormKey
        String propertySelectFormKey = getPropertyValueAsString(selectFormKey, elementNode);
        if (StringUtils.hasLength(propertySelectFormKey)) {
            ExtensionAttribute selectFormKeyAttr = new ExtensionAttribute();
            selectFormKeyAttr.setName(selectFormKey);
            selectFormKeyAttr.setValue(propertySelectFormKey);
            List<ExtensionAttribute> selectFormKeyAttrList = new ArrayList<>(1);
            selectFormKeyAttrList.add(selectFormKeyAttr);
            attributes.put(selectFormKey, selectFormKeyAttrList);
        }

//        selectPath
        String propertySelectPath = getPropertyValueAsString(selectPath, elementNode);
        if (StringUtils.hasLength(propertySelectPath)) {
            ExtensionAttribute selectPathAttr = new ExtensionAttribute();
            selectPathAttr.setName(selectPath);
            selectPathAttr.setValue(propertySelectPath);
            List<ExtensionAttribute> selectPathAttrList = new ArrayList<>(1);
            selectPathAttrList.add(selectPathAttr);
            attributes.put(selectPath, selectPathAttrList);
        }
        // assigneeType
        String propertyAssigneeType = getPropertyValueAsString(assigneeType, elementNode);
        if (StringUtils.hasLength(propertyAssigneeType)) {
            ExtensionAttribute assigneeTypeAttr = new ExtensionAttribute();
            assigneeTypeAttr.setName(assigneeType);
            assigneeTypeAttr.setValue(propertyAssigneeType);
            List<ExtensionAttribute> assigneeTypeList = new ArrayList<>(1);
            assigneeTypeList.add(assigneeTypeAttr);
            attributes.put(assigneeType, assigneeTypeList);
        }
        // relationNodeId
        String propertyRelationNodeId = getPropertyValueAsString(relationNodeId, elementNode);
        if (StringUtils.hasLength(propertyRelationNodeId)) {
            ExtensionAttribute relationNodeIdAttr = new ExtensionAttribute();
            relationNodeIdAttr.setName(relationNodeId);
            relationNodeIdAttr.setValue(propertyRelationNodeId);
            List<ExtensionAttribute> relationNodeIdList = new ArrayList<>(1);
            relationNodeIdList.add(relationNodeIdAttr);
            attributes.put(relationNodeId, relationNodeIdList);
        }
        // area
        String propertyArea = getPropertyValueAsString(area, elementNode);
        if (StringUtils.hasLength(propertyArea)) {
            ExtensionAttribute areaAttr = new ExtensionAttribute();
            areaAttr.setName(area);
            areaAttr.setValue(propertyArea);
            List<ExtensionAttribute> areaAttrList = new ArrayList<>(1);
            areaAttrList.add(areaAttr);
            attributes.put(area, areaAttrList);
        }
        // department
        String propertyDepartment = getPropertyValueAsString(department, elementNode);
        if (StringUtils.hasLength(propertyDepartment)) {
            ExtensionAttribute departmentAttr = new ExtensionAttribute();
            departmentAttr.setName(department);
            departmentAttr.setValue(propertyDepartment);
            List<ExtensionAttribute> departmentAttrList = new ArrayList<>(1);
            departmentAttrList.add(departmentAttr);
            attributes.put(department, departmentAttrList);
        }
        // role
        String propertyRole = getPropertyValueAsString(role, elementNode);
        if (StringUtils.hasLength(propertyRole)) {
            ExtensionAttribute roleAttr = new ExtensionAttribute();
            roleAttr.setName(role);
            roleAttr.setValue(propertyRole);
            List<ExtensionAttribute> roleAttrList = new ArrayList<>(1);
            roleAttrList.add(roleAttr);
            attributes.put(role, roleAttrList);
        }
        // roleIsAnd
        String propertyRoleIsAnd = getPropertyValueAsString(roleIsAnd, elementNode);
        if (StringUtils.hasLength(propertyRoleIsAnd)) {
            ExtensionAttribute roleIsAndAttr = new ExtensionAttribute();
            roleIsAndAttr.setName(roleIsAnd);
            roleIsAndAttr.setValue(propertyRoleIsAnd);
            List<ExtensionAttribute> roleIsAndList = new ArrayList<>(1);
            roleIsAndList.add(roleIsAndAttr);
            attributes.put(roleIsAnd, roleIsAndList);
        }
        // rule
        String propertyRule = getPropertyValueAsString(rule, elementNode);
        if (StringUtils.hasLength(propertyRule)) {
            ExtensionAttribute ruleAttr = new ExtensionAttribute();
            ruleAttr.setName(rule);
            ruleAttr.setValue(propertyRule);
            List<ExtensionAttribute> ruleAttrList = new ArrayList<>(1);
            ruleAttrList.add(ruleAttr);
            attributes.put(rule, ruleAttrList);
        }
        // userType
        String propertyUserType = getPropertyValueAsString(userType, elementNode);
        if (StringUtils.hasLength(propertyUserType)) {
            ExtensionAttribute userTypeAttr = new ExtensionAttribute();
            userTypeAttr.setName(userType);
            userTypeAttr.setValue(propertyUserType);
            List<ExtensionAttribute> userTypeAttrList = new ArrayList<>(1);
            userTypeAttrList.add(userTypeAttr);
            attributes.put(userType, userTypeAttrList);
        }
        // executeTimeLimit
        String propertyExecuteTimeLimit = getPropertyValueAsString(executeTimeLimit, elementNode);
        if (StringUtils.hasLength(propertyExecuteTimeLimit)) {
            ExtensionAttribute executeTimeLimitAttr = new ExtensionAttribute();
            executeTimeLimitAttr.setName(executeTimeLimit);
            executeTimeLimitAttr.setValue(propertyExecuteTimeLimit);
            List<ExtensionAttribute> executeTimeLimitList = new ArrayList<>(1);
            executeTimeLimitList.add(executeTimeLimitAttr);
            attributes.put(executeTimeLimit, executeTimeLimitList);
        }
        ee.setAttributes(attributes);

        userTask.addExtensionElement(ee);

        String propertyMultiLoop = getPropertyValueAsString(multiInstanceLoopCharacteristics, elementNode);
        if (StringUtils.hasLength(propertyMultiLoop)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = objectMapper.readValue(propertyMultiLoop, MultiInstanceLoopCharacteristics.class);
                // 必须与执行接口参数保持一致
                multiInstanceLoopCharacteristics.setInputDataItem("instances");
                userTask.setLoopCharacteristics(multiInstanceLoopCharacteristics);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }

        return userTask;
    }
}
